home *** CD-ROM | disk | FTP | other *** search
/ Clickx 96 / Clickx 96.iso / software / tools / tool / xbmc-10.1.exe / addons / script.module.pil / lib / PIL / BmpImagePlugin.py < prev    next >
Encoding:
Python Source  |  2009-06-13  |  6.7 KB  |  252 lines

  1. #
  2. # The Python Imaging Library.
  3. # $Id$
  4. #
  5. # BMP file handler
  6. #
  7. # Windows (and OS/2) native bitmap storage format.
  8. #
  9. # history:
  10. # 1995-09-01 fl   Created
  11. # 1996-04-30 fl   Added save
  12. # 1997-08-27 fl   Fixed save of 1-bit images
  13. # 1998-03-06 fl   Load P images as L where possible
  14. # 1998-07-03 fl   Load P images as 1 where possible
  15. # 1998-12-29 fl   Handle small palettes
  16. # 2002-12-30 fl   Fixed load of 1-bit palette images
  17. # 2003-04-21 fl   Fixed load of 1-bit monochrome images
  18. # 2003-04-23 fl   Added limited support for BI_BITFIELDS compression
  19. #
  20. # Copyright (c) 1997-2003 by Secret Labs AB
  21. # Copyright (c) 1995-2003 by Fredrik Lundh
  22. #
  23. # See the README file for information on usage and redistribution.
  24. #
  25.  
  26.  
  27. __version__ = "0.7"
  28.  
  29.  
  30. import string
  31. import Image, ImageFile, ImagePalette
  32.  
  33.  
  34. #
  35. # --------------------------------------------------------------------
  36. # Read BMP file
  37.  
  38. def i16(c):
  39.     return ord(c[0]) + (ord(c[1])<<8)
  40.  
  41. def i32(c):
  42.     return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
  43.  
  44.  
  45. BIT2MODE = {
  46.     # bits => mode, rawmode
  47.     1: ("P", "P;1"),
  48.     4: ("P", "P;4"),
  49.     8: ("P", "P"),
  50.     16: ("RGB", "BGR;15"),
  51.     24: ("RGB", "BGR"),
  52.     32: ("RGB", "BGRX")
  53. }
  54.  
  55. def _accept(prefix):
  56.     return prefix[:2] == "BM"
  57.  
  58. ##
  59. # Image plugin for the Windows BMP format.
  60.  
  61. class BmpImageFile(ImageFile.ImageFile):
  62.  
  63.     format = "BMP"
  64.     format_description = "Windows Bitmap"
  65.  
  66.     def _bitmap(self, header = 0, offset = 0):
  67.  
  68.         if header:
  69.             self.fp.seek(header)
  70.  
  71.         read = self.fp.read
  72.  
  73.         # CORE/INFO
  74.         s = read(4)
  75.         s = s + ImageFile._safe_read(self.fp, i32(s)-4)
  76.  
  77.         if len(s) == 12:
  78.  
  79.             # OS/2 1.0 CORE
  80.             bits = i16(s[10:])
  81.             self.size = i16(s[4:]), i16(s[6:])
  82.             compression = 0
  83.             lutsize = 3
  84.             colors = 0
  85.             direction = -1
  86.  
  87.         elif len(s) in [40, 64]:
  88.  
  89.             # WIN 3.1 or OS/2 2.0 INFO
  90.             bits = i16(s[14:])
  91.             self.size = i32(s[4:]), i32(s[8:])
  92.             compression = i32(s[16:])
  93.             lutsize = 4
  94.             colors = i32(s[32:])
  95.             direction = -1
  96.             if s[11] == '\xff':
  97.                 # upside-down storage
  98.                 self.size = self.size[0], 2**32 - self.size[1]
  99.                 direction = 0
  100.  
  101.         else:
  102.             raise IOError("Unsupported BMP header type (%d)" % len(s))
  103.  
  104.         if not colors:
  105.             colors = 1 << bits
  106.  
  107.         # MODE
  108.         try:
  109.             self.mode, rawmode = BIT2MODE[bits]
  110.         except KeyError:
  111.             raise IOError("Unsupported BMP pixel depth (%d)" % bits)
  112.  
  113.         if compression == 3:
  114.             # BI_BITFIELDS compression
  115.             mask = i32(read(4)), i32(read(4)), i32(read(4))
  116.             if bits == 32 and mask == (0xff0000, 0x00ff00, 0x0000ff):
  117.                 rawmode = "BGRX"
  118.             elif bits == 16 and mask == (0x00f800, 0x0007e0, 0x00001f):
  119.                 rawmode = "BGR;16"
  120.             elif bits == 16 and mask == (0x007c00, 0x0003e0, 0x00001f):
  121.                 rawmode = "BGR;15"
  122.             else:
  123.                 # print bits, map(hex, mask)
  124.                 raise IOError("Unsupported BMP bitfields layout")
  125.         elif compression != 0:
  126.             raise IOError("Unsupported BMP compression (%d)" % compression)
  127.  
  128.         # LUT
  129.         if self.mode == "P":
  130.             palette = []
  131.             greyscale = 1
  132.             if colors == 2:
  133.                 indices = (0, 255)
  134.             else:
  135.                 indices = range(colors)
  136.             for i in indices:
  137.                 rgb = read(lutsize)[:3]
  138.                 if rgb != chr(i)*3:
  139.                     greyscale = 0
  140.                 palette.append(rgb)
  141.             if greyscale:
  142.                 if colors == 2:
  143.                     self.mode = rawmode = "1"
  144.                 else:
  145.                     self.mode = rawmode = "L"
  146.             else:
  147.                 self.mode = "P"
  148.                 self.palette = ImagePalette.raw(
  149.                     "BGR", string.join(palette, "")
  150.                     )
  151.  
  152.         if not offset:
  153.             offset = self.fp.tell()
  154.  
  155.         self.tile = [("raw",
  156.                      (0, 0) + self.size,
  157.                      offset,
  158.                      (rawmode, ((self.size[0]*bits+31)>>3)&(~3), direction))]
  159.  
  160.         self.info["compression"] = compression
  161.  
  162.     def _open(self):
  163.  
  164.         # HEAD
  165.         s = self.fp.read(14)
  166.         if s[:2] != "BM":
  167.             raise SyntaxError("Not a BMP file")
  168.         offset = i32(s[10:])
  169.  
  170.         self._bitmap(offset=offset)
  171.  
  172.  
  173. class DibImageFile(BmpImageFile):
  174.  
  175.     format = "DIB"
  176.     format_description = "Windows Bitmap"
  177.  
  178.     def _open(self):
  179.         self._bitmap()
  180.  
  181. #
  182. # --------------------------------------------------------------------
  183. # Write BMP file
  184.  
  185. def o16(i):
  186.     return chr(i&255) + chr(i>>8&255)
  187.  
  188. def o32(i):
  189.     return chr(i&255) + chr(i>>8&255) + chr(i>>16&255) + chr(i>>24&255)
  190.  
  191. SAVE = {
  192.     "1": ("1", 1, 2),
  193.     "L": ("L", 8, 256),
  194.     "P": ("P", 8, 256),
  195.     "RGB": ("BGR", 24, 0),
  196. }
  197.  
  198. def _save(im, fp, filename, check=0):
  199.  
  200.     try:
  201.         rawmode, bits, colors = SAVE[im.mode]
  202.     except KeyError:
  203.         raise IOError("cannot write mode %s as BMP" % im.mode)
  204.  
  205.     if check:
  206.         return check
  207.  
  208.     stride = ((im.size[0]*bits+7)/8+3)&(~3)
  209.     header = 40 # or 64 for OS/2 version 2
  210.     offset = 14 + header + colors * 4
  211.     image  = stride * im.size[1]
  212.  
  213.     # bitmap header
  214.     fp.write("BM" +                     # file type (magic)
  215.              o32(offset+image) +        # file size
  216.              o32(0) +                   # reserved
  217.              o32(offset))               # image data offset
  218.  
  219.     # bitmap info header
  220.     fp.write(o32(header) +              # info header size
  221.              o32(im.size[0]) +          # width
  222.              o32(im.size[1]) +          # height
  223.              o16(1) +                   # planes
  224.              o16(bits) +                # depth
  225.              o32(0) +                   # compression (0=uncompressed)
  226.              o32(image) +               # size of bitmap
  227.              o32(1) + o32(1) +          # resolution
  228.              o32(colors) +              # colors used
  229.              o32(colors))               # colors important
  230.  
  231.     fp.write("\000" * (header - 40))    # padding (for OS/2 format)
  232.  
  233.     if im.mode == "1":
  234.         for i in (0, 255):
  235.             fp.write(chr(i) * 4)
  236.     elif im.mode == "L":
  237.         for i in range(256):
  238.             fp.write(chr(i) * 4)
  239.     elif im.mode == "P":
  240.         fp.write(im.im.getpalette("RGB", "BGRX"))
  241.  
  242.     ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, stride, -1))])
  243.  
  244. #
  245. # --------------------------------------------------------------------
  246. # Registry
  247.  
  248. Image.register_open(BmpImageFile.format, BmpImageFile, _accept)
  249. Image.register_save(BmpImageFile.format, _save)
  250.  
  251. Image.register_extension(BmpImageFile.format, ".bmp")
  252.